package httpclient

import (
	"context"
	"net/http"
)

// ContextualMiddlewareName is the middleware name used by ContextualMiddleware.
const ContextualMiddlewareName = "contextual-middleware"

func ContextualMiddleware() Middleware {
	return NamedMiddlewareFunc(ContextualMiddlewareName, func(opts Options, next http.RoundTripper) http.RoundTripper {
		return RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
			ctxMiddlewares := ContextualMiddlewareFromContext(req.Context())
			if len(ctxMiddlewares) == 0 {
				return next.RoundTrip(req)
			}

			return roundTripperFromMiddlewares(opts, ctxMiddlewares, next).RoundTrip(req)
		})
	})
}

type contextualMiddlewareValue struct {
	middlewares []Middleware
}

type contextualMiddlewareKey struct{}

func WithContextualMiddleware(parent context.Context, middlewares ...Middleware) context.Context {
	if len(middlewares) == 0 {
		middlewares = []Middleware{}
	}
	existingMiddlewares := ContextualMiddlewareFromContext(parent)

	if len(existingMiddlewares) > 0 {
		middlewares = append(existingMiddlewares, middlewares...)
	}
	return context.WithValue(parent, contextualMiddlewareKey{}, contextualMiddlewareValue{
		middlewares: middlewares,
	})
}

// ContextualMiddlewareFromContext
//
// 这个函数从给定的上下文中获取与语境相关的中间件，并返回一个中间件切片。如果上下文中不存在相关值，则返回一个空的中间件切片。
func ContextualMiddlewareFromContext(ctx context.Context) []Middleware {
	v := ctx.Value(contextualMiddlewareKey{})
	if v == nil {
		return []Middleware{}
	}

	if opts, ok := v.(contextualMiddlewareValue); ok {
		return opts.middlewares
	}
	return []Middleware{}

}
